%{
   #include "ts.h" /* Contains definition of ‘symrec'. */

   enum yytokentype {
   IDENTIFICADOR     = 256,		
   ENTERO            = 257,
   CHAR		     = 258,
   CONST	     = 259,
   INT		     = 265,
   INT1		     = 266,
   INT2		     = 267,
   INT3		     = 268,
   INT4		     = 269,
   INT5		     = 270,
   INT6		     = 271,
   INT7		     = 272,
   INT8		     = 273,
   VOID		     = 274,
   MAIN		     = 280,
   MALLOC	     = 285,
   DELETE	     = 286,
   IF                = 290,
   ELSE              = 291,
   SWITCH            = 295,
   CASE              = 296,
   BREAK             = 297,
   DEFAULT           = 300,
   DO                = 305,
   WHILE             = 306,
   FOR               = 310,
   RETURN	     = 315,
   CONTINUE	     = 316,
   EXIT	    	     = 320,
   PRINTF	     = 325,
   OPASIG            = 330,
   SUMA		     = 331,
   RESTA	     = 332,
   MULTIPLICACION    = 333,
   DIVISION	     = 334,
   MODULO	     = 335,
   SUMA_ASIG	     = 340,
   MULTIPLICA_ASIG   = 341,		
   OPLOG             = 342,
   MEN               = 343,
   MEI               = 344,
   MAY               = 345,		
   MAI               = 346,
   COMP              = 347,
   O_LOG	     = 348,
   Y_LOG	     = 349,
   NOT               = 350,
   DIF               = 351,
   INCREMENTO        = 355,
   DECREMENTO        = 356,
   COMA		     = 360,
   DOS_PUNTOS	     = 361,
   FIN_SENTENCIA     = 362,
   PARENTESIS_ABRE   = 365,
   PARENTESIS_CIERRA = 366,
   CORCHETE_ABRE     = 367,	
   CORCHETE_CIERRA   = 368,
   LLAVE_ABRE        = 369,
   LLAVE_CIERRA      = 370,
   O_BIT	     = 380,
   Y_BIT	     = 381,
   O_ASIGBIT	     = 382,
   Y_ASIGBIT	     = 383,
   COMENTARIO	     = 385,
   CADENA	     = 386

   };

   float yylval;
   
	/* Tabla de símbolos: Lista de nodos 'nodo_ts' */
	token *ts;
%}

/* Universal Character Name: the naming conventions for UCS defined by International Standard ISO/IEC 10646 */
UCN     		(\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8})
obviar         [" " \n\t]+
letra_         [A-Za-z_]
digito         [0-9]
identificador  {letra_}({letra_}|{digito})*
entero         [+-]?{digito}+(\.{digito}*)?(E[+-]?{digito}+)?
real		   entero"."entero
cadena	       L?\"([^"\\]|\\['"?\\abfnrtv]|\\[0-7]{1,3}|\\[Xx][0-9a-fA-F]+|{UCN})*\"
incremento     [++]
decremento     [--]
/* %x commentaario */
comentario    ("/*"([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*"*"+"/")|("//".*)

%%

	/* --------------------------------- */
	/* 	  OPERADORES Y SIGNOS        */
	/* --------------------------------- */
"<="           { yylval = MEI; return(OPLOG); }
">"            { yylval = MAY; return(OPLOG); }
">="           { yylval = MAI; return(OPLOG); }
"<"            { yylval = MEN; return(OPLOG); }
"!="           { yylval = DIF; return(OPLOG); }
"!"            { yylval = NOT; return(OPLOG); }    
"=="           { yylval = COMP; return(OPLOG); }
"||"	       { yylval = O_LOG; return(OPLOG); }
"&&"	       { yylval = Y_LOG; return(OPLOG); }
"|"	       { yylval = O_BIT; return(OPLOG); }
"&"	       { yylval = Y_BIT; return(OPLOG); }
"="            { return OPASIG; }
"+"	       { return SUMA; }
"-"	       { return RESTA; }
"*"	       { return MULTIPLICACION; }
"/"	       { return DIVISION; }
"%"	       { return MODULO; }
"|="	       { return O_ASIGBIT; }
"&="	       { return Y_ASIGBIT; }
"+="	       { return SUMA_ASIG; }
"*="	       { return MULTIPLICA_ASIG; }
"++"           { return INCREMENTO; }
"--"           { return DECREMENTO; }
","	       { return COMA; }
":"	       { return DOS_PUNTOS; }
";"            { return FIN_SENTENCIA; }
"("            { return PARENTESIS_ABRE; }
")"            { return PARENTESIS_CIERRA; }
"["	       { return CORCHETE_ABRE; }
"]"	       { return CORCHETE_CIERRA; }
"{"            { return LLAVE_ABRE; }
"}"            { return LLAVE_CIERRA; }

	/* --------------------------------- */
	/* 	   PALABRAS RESERVADAS	     */
	/* --------------------------------- */
if             { printf("<IF>\n");}
else           { printf("<ELSE>\n");}
switch         { printf("<SWITCH>\n");}
case           { printf("<CASE>\n");}
break          { printf("<BREAK>\n");}
default        { printf("<DEFAULT>\n");}
do             { printf("<DO>\n");}
while          { printf("<WHILE>\n");}
for            { printf("<FOR>\n");}
return	       { printf("<RETURN>\n");}
continue       { printf("<CONTINUE>\n");}
exit	       { printf("<EXIT>\n");}
printf	       { printf("<PRINTF>\n");}
char	       { printf("<CHAR>\n");}
const	       { printf("<CONST>\n");}
int	       { printf("<INT>\n");}
int1	       { printf("<INT1>\n");}
int2	       { printf("<INT2>\n");}
int3	       { printf("<INT3>\n");}
int4	       { printf("<INT4>\n");}
int5	       { printf("<INT5>\n");}
int6	       { printf("<INT6>\n");}
int7	       { printf("<INT7>\n");}
int8	       { printf("<INT8>\n");}
void	       { printf("<VOID>\n");}
main	       { printf("<MAIN>\n");}
malloc	       { printf("<MALLOC>\n");}
delete	       { printf("<DELETE>\n");}

	/* --------------------------------- */
	/* 	      IDENTIFICADORES	     */
	/* --------------------------------- */
{identificador}     { return IDENTIFICADOR; }

	/* --------------------------------- */
	/* 	      LITERALES		     */
	/* --------------------------------- */
{obviar}       { }
{real}         { }
{entero}       { yylval = atof(yytext); return ENTERO; }
{cadena}       { return CADENA;}
{comentario}   { return COMENTARIO; }

%%

/* Tabla de símbolos: Lista de nodos tipo token. */
token *ts;

/* 
   Inicialización de la tabla de símbolos:
   1.- Copiado de las palabras reservadas del lenguaje.
*/

void init_table (void) {
   int i;
   token *ptr;
   
   ptr = putToken ("if", IF, 0.0);
   ptr = putToken ("else", ELSE, 0.0);
   ptr = putToken ("switch", SWITCH, 0.0);
   ptr = putToken ("case", CASE, 0.0);
   ptr = putToken ("break", BREAK,0.0);
   ptr = putToken ("default", DEFAULT, 0.0);
   ptr = putToken ("do", DO, 0.0);
   ptr = putToken ("while", WHILE, 0.0);
   ptr = putToken ("for", FOR, 0.0);
   ptr = putToken ("return", RETURN, 0.0);
   ptr = putToken ("continue", CONTINUE, 0.0);
   ptr = putToken ("exit", EXIT, 0.0);
   ptr = putToken ("char", CHAR, 0.0);
   ptr = putToken ("const", CONST, 0.0);
   ptr = putToken ("int", INT, 0.0);
   ptr = putToken ("int1", INT1, 0.0);
   ptr = putToken ("int2", INT2, 0.0);
   ptr = putToken ("int3", INT3, 0.0);
   ptr = putToken ("int4", INT4, 0.0);
   ptr = putToken ("int5", INT5, 0.0);
   ptr = putToken ("int6", INT6, 0.0);
   ptr = putToken ("int7", INT7, 0.0);
   ptr = putToken ("int8", INT8, 0.0);
   ptr = putToken ("void", VOID, 0.0);
   ptr = putToken ("main", MAIN, 0.0);
   ptr = putToken ("malloc", MALLOC, 0.0);
   ptr = putToken ("delete", DELETE, 0.0);
}

token * putToken (char const *name, int type, double value) {
   token *ptr;
   ptr = (token *) malloc (sizeof (token));
   
   ptr->nombre = (char *) malloc (strlen (name) + 1);
   strcpy (ptr->nombre, name);
   ptr->tipo = type;
   ptr->valor.numero = value;

   ptr->next = (struct token *) ts;
   ts = ptr;
   return ptr;
}

token * getToken (char const *name) {
   token *ptr;
   for (ptr = ts; ptr != (token *) 0; ptr = (token *)ptr->next)
      if (strcmp (ptr->nombre, name) == 0)
         return ptr;
   return 0;
}

void deleteTS() {
   token *ptr;
   
   while(ts != (token *) 0) {
      ptr = ts->next;
      free(ts);
      ts = ptr;
   }
}

void showTS() {
   token *ptr = ts;
   
   printf("\nTokens almacenados en la tabla de símbolos:\n");
   
   while(ptr != (token *) 0) {
      if(ptr->tipo == IF)
    {
      printf("<IF>");
    }
    else 
    if(ptr->tipo == ELSE)
    {
      printf("<ELSE>");
    }
    else
      if(ptr->tipo == SWITCH)
    {
      printf("<SWITCH>");
    }
    else 
    if(ptr->tipo == CASE)
    {
      printf("<CASE>");
    } 
    else
    if (ptr->tipo == BREAK)
    {
      printf("<BREAK>");
    }
    else
    if (ptr->tipo == DEFAULT)
    {
      printf("<DEFAULT>");
    }
    else 
    if (ptr->tipo == DO)
    {
      printf("<DO>");
    }
    else
    if (ptr->tipo == WHILE)
    {
      printf("<WHILE>");
    }
    else
      if (ptr->tipo == FOR) {
         printf("<FOR>");
      } else
      if (ptr->tipo == RETURN) {
         printf("<RETURN>");
      } else
      if (ptr->tipo == CONTINUE) {
         printf("<CONTINUE>");
      } else
      if (ptr->tipo == EXIT) {
         printf("<EXIT>");
      } else
      if (ptr->tipo == CHAR) {
         printf("<CHAR>");
      } else
      if (ptr->tipo == CONST) {
         printf("<CONST>");
      } else
      if (ptr->tipo == INT) {
         printf("<INT>");
      } else
      if (ptr->tipo == INT1) {
         printf("<INT1>");
      } else
      if (ptr->tipo == INT2) {
         printf("<INT2>");
      } else
      if (ptr->tipo == INT3) {
         printf("<INT3>");
      } else
      if (ptr->tipo == INT4) {
         printf("<INT4>");
      } else
      if (ptr->tipo == INT5) {
         printf("<INT5>");
      } else
      if (ptr->tipo == INT6) {
         printf("<INT6>");
      } else
      if (ptr->tipo == INT7) {
         printf("<INT7>");
      } else
      if (ptr->tipo == INT8) {
         printf("<INT8>");
      } else
      if (ptr->tipo == VOID) {
         printf("<VOID>");
      } else
      if (ptr->tipo == MAIN) {
         printf("<MAIN>");
      } else
      if (ptr->tipo == MALLOC) {
         printf("<MALLOC>");
      } else
      if (ptr->tipo == DELETE) {
         printf("<DELETE>");
      } else
      if (ptr->tipo == PRINTF) {
         printf("<PRINTF>");
      } else 
      if (ptr->tipo == IDENTIFICADOR) {
         printf("<IDENTIFICADOR,%s>",ptr->nombre);
      } else {
         printf("Error: Tipo de token desconocido.");
      }
      ptr = ptr->next;
      printf("\n");
   }
   printf("\n");
}

main(int argc, char **argv) {
   int tok;

   if(argc > 1) {
      if(!(yyin = fopen(argv[1], "r"))) {
         printf("ERROR: El archivo de entrada no pudo ser leído.\n");
         exit(0);
      }
   }

   init_table ();

   while(tok=yylex()) {
      if(tok== INCREMENTO) {
         printf("<INCREMENTO>");
      } else
      if(tok==OPLOG) {
         printf("<OPLOG,%i>",(int)yylval);
      } else
      if(tok==OPASIG) {
         printf("<OPASIG>");
      } else
      if(tok== SUMA ){
      	printf("<SUMA>");
      }else
      if(tok== RESTA ){
      	printf("<RESTA>");
      }else
      if(tok== MULTIPLICACION ){
      	printf("<MULTIPLICACION>");
      }else
      if(tok== DIVISION ){
      	printf("<DIVISION>");
      }else
       if(tok== MODULO ){
      	printf("<MODULO>");
      }else
      if(tok== O_ASIGBIT ){
      	printf("<O_ASIGBIT>");
      }else
      if(tok== Y_ASIGBIT ){
      	printf("<Y_ASIGBIT>");
      }else      
      if(tok== SUMA_ASIG ){
      	printf("<SUMA_ASIG>");
      }else
      if(tok== MULTIPLICA_ASIG ){
      	printf("<MULTIPLICA_ASIG>");
      }else
      if(tok== COMA ){
      	printf("<COMA>");
      }else  
       if(tok== DOS_PUNTOS ){
      	printf("<DOS_PUNTOS>");
      }else            
      if(tok== DECREMENTO) {
         printf("<DECREMENTO>");
      } else
      if(tok== FIN_SENTENCIA) {
         printf("<FIN_SENTENCIA>");
      } else
      if(tok== PARENTESIS_ABRE) {
         printf("<PARENTESIS_ABRE>");
      } else
      if(tok== PARENTESIS_CIERRA) {
         printf("<PARENTESIS_CIERRA>");
      } else
      if(tok== CORCHETE_ABRE){
      	printf("<CORCHETE_ABRE>");
      }else
      if(tok== CORCHETE_CIERRA){
      	printf("<CORCHETE_CIERRA>");
      }else
      if(tok== LLAVE_ABRE) {
         printf("<LLAVE_ABRE>");
      } else
      if(tok== LLAVE_CIERRA) {
         printf("<LLAVE_CIERRA>");
      } else
      if(tok== COMENTARIO){
      	printf("<COMENTARIO>");
      }else
      if(tok== CADENA){
    	 printf("<CADENA CTTE: %s>", yytext);
      }else
      if (tok== PRINTF) {
         printf("<PRINTF>");
      } else
      if(tok==ENTERO) {      
         printf("<ENTERO,%.2f>",yylval);
      } else
      if(tok==IDENTIFICADOR) {      
         token *t;
         t = getToken (yytext);
         if (t == 0) {
            t = putToken (yytext, IDENTIFICADOR, 0.0); 
            printf("<IDENTIFICADOR,%s>",yytext);
         } else {
            if (t->tipo == IF) {
             printf("<IF>");
           } else
           if (t->tipo == ELSE) {
              printf("<ELSE>");
           } else
           if (t->tipo == SWITCH) {
              printf("<SWITCH>");
           } else
           if (t->tipo == CASE) {
              printf("<CASE>");
           } else
           if (t->tipo == BREAK) {
              printf("<BREAK>");
           } else         
           if (t->tipo == DEFAULT) {
              printf("<DEFAULT>");
           }else
           if (t->tipo == DO) {
              printf("<DO>");
           } else
           if (t->tipo == WHILE) {
              printf("<WHILE>");
           } else
           if (t->tipo == FOR) {
               printf("<FOR>");
            } else
            if (t->tipo == RETURN) {
               printf("<RETURN>");
            } else
            if (t->tipo == CONTINUE) {
               printf("<CONTINUE>");
            } else
            if (t->tipo == EXIT) {
               printf("<EXIT>");
            } else
            if (t->tipo == CHAR) {
               printf("<CHAR>");
            } else
            if (t->tipo == CONST) {
               printf("<CONST>");
            } else
            if (t->tipo == INT) {
               printf("<INT>");
            } else
            if (t->tipo == INT1) {
               printf("<INT1>");
            } else
            if (t->tipo == INT2) {
               printf("<INT2>");
            } else
            if (t->tipo == INT3) {
               printf("<INT3>");
            } else 
            if (t->tipo == INT4) {
               printf("<INT4>");
            } else
            if (t->tipo == INT5) {
               printf("<INT5>");
            } else
            if (t->tipo == INT6) {
               printf("<INT6>");
            } else
            if (t->tipo == INT7) {
               printf("<INT7>");
            } else 
            if (t->tipo == INT8) {
               printf("<INT8>");
            } else
            if (t->tipo == VOID) {
               printf("<VOID>");
            } else
            if (t->tipo == MAIN) {
               printf("<MAIN>");
            } else
            if (t->tipo == MALLOC) {
               printf("<MALLOC>");
            } else
            if (t->tipo == DELETE) {
               printf("<DELETE>");
            } else {
               printf("<IDENTIFICADOR,%s>",yytext);
            }
         }         
      } else {
         printf("¡ERROR! Cadena no reconocida: %s", yytext);
      }

      printf("\n");
   }
   
   showTS();
   deleteTS();
}

